home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / et / et3_0-a1.lha / et3 / src / StyledText.C < prev    next >
C/C++ Source or Header  |  1992-08-20  |  12KB  |  484 lines

  1. #ifdef __GNUG__
  2. #pragma implementation
  3. #endif
  4.  
  5. #include "StyledText.h"
  6.  
  7. #include "Class.h"
  8. #include "WindowSystem.h"
  9. #include "RunArray.h"
  10. #include "Mark.h"
  11. #include "OrdColl.h"
  12. #include "Error.h"
  13. #include "Invariant.h"
  14. #include "TextReader.h"
  15. #include "Math.h"
  16.  
  17. extern "C" void REP(StyledText *st);
  18.  
  19. void REP(StyledText *st)
  20. {
  21.     st->Dump();
  22. }
  23.  
  24. InvariantChecker(StyledText);
  25.  
  26. //----- colors for BuildStylesFromString --------------------------------------
  27.  
  28. Ink *red, *green, *blue;
  29.  
  30. //----- StyledText -------------------------------------------------------------
  31.  
  32. NewMetaImpl(StyledText,GapText, (TP(charStyles), TP(paraStyles), 
  33.                TP(styleHere), T(applyStyleHere)));    
  34.  
  35. static TextChanges changeRec;
  36.  
  37. StyledText::StyledText(int size, Font *fd, TxtParaAlign al) : GapText(size, fd)
  38. {
  39.     InitStyles(new_CharStyle(fd), new_ParaStyle(al));
  40. }
  41.  
  42. StyledText::StyledText(byte *buf, int len, Font *fd, TxtParaAlign al)  
  43.                              : GapText(buf, len, fd)
  44. {
  45.     InitStyles(new_CharStyle(fd), new_ParaStyle(al));
  46. }
  47.  
  48. StyledText::StyledText(Font *fd, char* va_(fmt), ...)
  49. {
  50.     char *buf;
  51.  
  52.     va_list ap;
  53.     va_start(ap,va_(fmt));
  54.     buf= strvprintf(va_(fmt), ap);
  55.     va_end(ap);
  56.     
  57.     InitStyles(new_CharStyle(fd), new_ParaStyle());
  58.     BuildStylesFromString(new_CharStyle(fd), buf);
  59.     SafeDelete(buf);
  60. }
  61.  
  62. StyledText::~StyledText()
  63. {
  64.     SafeDelete(charStyles);
  65.     SafeDelete(paraStyles);
  66. }
  67.  
  68. void StyledText::InitNew()
  69. {
  70.     GapText::InitNew();
  71.     InitStyles(new_CharStyle(gSysFont), new_ParaStyle());
  72. }
  73.  
  74. void StyledText::InitStyles(CharStyle *cs, ParaStyle *ps)
  75. {
  76.     charStyles= new RunArray;
  77.     paraStyles= new RunArray;
  78.     applyStyleHere= FALSE;
  79.         
  80.     paraStyles->Insert(ps, 0, 0, Size());
  81.     charStyles->Insert(cs, 0, 0, Size());
  82. }
  83.  
  84. int StyledText::GetNextFontChange(int at, CharStyle *&sp)
  85.     int start, end, size, lenat;
  86.     at= Math::Range(0, Size()-1, at);
  87.     sp= (CharStyle*)charStyles->RunAt(at, &start, &end, &size, &lenat);
  88.     return at+lenat;
  89. }
  90.  
  91. void StyledText::ReplaceWithStr(byte *str,int len)
  92. {
  93.     GapText::ReplaceWithStr(str, len);
  94.     SafeDelete(charStyles);
  95.     SafeDelete(paraStyles);
  96.     InitStyles(new_CharStyle(GetFont()), new_ParaStyle());   
  97. }
  98.  
  99. void StyledText::Cut(int from, int to)
  100. {
  101.     int start, end, size, lenat;
  102.     CharStyle *sp= (CharStyle*)charStyles->RunAt(from, &start, &end, &size, &lenat);
  103.     applyStyleHere= FALSE;
  104.     if (start == from && size <= to - from) {
  105.     applyStyleHere= TRUE;
  106.     styleHere= sp;
  107.     }
  108.     GapText::Cut(from, to);
  109. }
  110.  
  111. void StyledText::Dump()
  112. {
  113.     RunArrayIter next(paraStyles);
  114.     int start, end, size, i;
  115.     
  116.     fprintf(stderr, "DUMP\n");
  117.     fprintf(stderr, "Runs\n");
  118.     for (i= 0; next.Run(&start, &end, &size) != 0; i++) {
  119.     fprintf(stderr, "%d ", end);
  120.     if (!IsBreak(CharAt(end-1)))
  121.         fprintf(stderr, "!");
  122.     }
  123.     fprintf(stderr, "\n");
  124. }
  125.  
  126. void StyledText::CheckInvariant()
  127. {
  128.     if (GetAssertLevel() > 10)
  129.     return;
  130.  
  131.     RunArrayIter next(paraStyles);
  132.     int start, end, size, i;
  133.     
  134.     if (paraStyles->Size() != Size()) {
  135.     fprintf(stderr, "!!!StyledText Invariant: paraStyles: size differs! %d %d\n", paraStyles->Size(), Size());
  136.     Dump();
  137.     }
  138.     if (charStyles->Size() != Size()) {
  139.     fprintf(stderr, "!!!StyledText Invariant: charStyles: size differs! %d %d\n", paraStyles->Size(), Size());
  140.     Dump();
  141.     }
  142.     for (i= 0; next.Run(&start, &end, &size) != 0; i++) {
  143.     if (!IsBreak(CharAt(end-1)) && end < Size()) {
  144.         fprintf(stderr, "!!!StyledText Invariant: no paragraph at %d\n", end-1);
  145.         Dump();
  146.     }
  147.     }
  148. }
  149.  
  150. void StyledText::CutParaStyles(int from, int to, int sz)
  151. {
  152.     int pfl, pfr;
  153.     
  154.     GetParaRange(from, &pfl, &pfr);
  155.     paraStyles->Cut(from, to);
  156.     paraStyles->ChangeRunSize(from, sz, eRARight);
  157.     if(pfl < Size()) {
  158.     ParaStyle *ps= GetParaStyle(pfl);
  159.     paraStyles->Insert(ps, from, pfr, pfr-from);
  160.     }
  161. }
  162.  
  163. void StyledText::ReplaceRange(int from, int to, Text* src, int sfrom, int sto)
  164. {
  165.     AssertInvariant(StyledText);
  166.     int sz= sto-sfrom;
  167.     
  168.     DoDelayChanges dc(this);
  169.     
  170.     GapText::ReplaceRange(from, to, src, sfrom, sto);
  171.     if (src->IsKindOf(StyledText)) { 
  172.     StyledText *st= (StyledText*) src;
  173.     charStyles->ReplaceRange(from, to, st->charStyles, sfrom, sto);
  174.     PasteParaStyles(from, to, st->paraStyles, sfrom, sto);
  175.     return;
  176.     }
  177.     if (from != to) 
  178.     CutStyles(from, to, sz);
  179.     else
  180.     paraStyles->ChangeRunSize(from, sz, eRARight);
  181.     
  182.     if (applyStyleHere && sz) { // insert new run with styleHere
  183.     charStyles->Insert(styleHere, from, from, sz);
  184.     applyStyleHere= FALSE;
  185.     } else 
  186.     AddChars(from, sz);
  187. }
  188.  
  189. void StyledText::CutStyles(int from, int to, int sz)
  190. {
  191.     int start, end, size, lenat;
  192.     CharStyle *sp= (CharStyle*)charStyles->RunAt(from, &start, &end, &size, &lenat);
  193.     if (start == from && size <= to - from) {
  194.     applyStyleHere= TRUE;
  195.     styleHere= sp;
  196.     }
  197.     CutParaStyles(from, to, sz);
  198.     charStyles->Cut(from, to);
  199. }
  200.  
  201. void StyledText::PasteParaStyles(int from, int to, RunArray *pr, int sfrom, int sto)
  202. {
  203.     int pfl, pfr, ptl, ptr, sz= sto-sfrom; 
  204.     ParaStyle *ps;
  205.     
  206.     paraStyles->ReplaceRange(from, to, pr, sfrom, sto);
  207.     
  208.     GetParaRange(from, &pfl, &pfr);
  209.     GetParaRange(from+sz, &ptl, &ptr);
  210.     
  211.     if(pfl == ptl) {
  212.     ps= GetParaStyle(from+sz);
  213.     paraStyles->Insert(ps, from, from+sz, sz);
  214.     } else {
  215.     ps= GetParaStyle(pfl);
  216.     paraStyles->Insert(ps, from, pfr, pfr-from);
  217.     ps= GetParaStyle(ptl);
  218.     paraStyles->Insert(ps, from+sz, ptr, ptr-from-sz);
  219.     }
  220. }
  221.  
  222. void StyledText::AddChars(int at, int sz)
  223. {
  224.     RArrayGrowDir g= eRALeft;
  225.     if (IsParaStart(at))
  226.     g= eRARight;
  227.     charStyles->ChangeRunSize(at, sz, g);
  228. }
  229.  
  230. void StyledText::SetFStringVL(char *fmt, va_list ap)
  231. {
  232.     char *buf= strvprintf(fmt, ap);
  233.     
  234.     CharStyle *st= GetCharStyle(0);
  235.     BuildStylesFromString(st, buf);
  236.     SafeDelete(buf);
  237. }
  238.  
  239. OStream &StyledText::PrintOn(OStream &s) 
  240. {
  241.     AssertInvariant(StyledText);
  242.     GapText::PrintOn(s);
  243.     return s << charStyles SP << paraStyles SP;
  244. }
  245.  
  246. IStream &StyledText::ReadFrom(IStream &s) 
  247. {
  248.     AssertInvariant(StyledText);
  249.     GapText::ReadFrom(s);
  250.     s >> charStyles >> paraStyles;
  251.     return s;
  252. }
  253.  
  254. IStream& StyledText::ReadFromAsPureText(IStream &s, long sizeHint)
  255. {
  256.     GapText::ReadFromAsPureText(s, sizeHint);
  257.     SafeDelete(paraStyles);
  258.     SafeDelete(charStyles);
  259.     InitStyles(new_CharStyle(GapText::GetFont(0)), new_ParaStyle());
  260.     return s;
  261. }
  262.  
  263. void StyledText::SetCharStyle(TxtCharProp what, int from, int to, const CharStyleSpec &st)
  264. {
  265.     int start, end, size;
  266.  
  267.     if (from == to) {
  268.     CharStyle *sp= applyStyleHere ? styleHere : GetCharStyle(Math::Max(0, from-1));
  269.     applyStyleHere= TRUE;
  270.     styleHere= gCharStyles->ChangeProperty(sp, what, st);
  271.     } else {
  272.     CharStyle **spp;
  273.     RunArray newStyles(2); 
  274.     charStyles->Copy(&newStyles, from, to);
  275.     RunArrayIter next(&newStyles);
  276.     while (spp= (CharStyle**)next.RunPtr(&start, &end, &size)) 
  277.         *spp= gCharStyles->ChangeProperty(*spp, what, st);
  278.     charStyles->Paste(&newStyles, from, to);
  279.     
  280.     GetMarkList()->RangeChanged(from, to - from);
  281.     Send(cIdNone, eTextChangedRange, changeRec(from, to));     
  282.     }
  283. }
  284.   
  285. void StyledText::BuildStylesFromString(CharStyle *cs, char *buf)
  286. {
  287.     TextReader *reader= new TextReader(this, cs, new_ParaStyle());
  288.  
  289.     if (gColor) {
  290.     red= new_RGBColor(255, 0, 0);
  291.     green= new_RGBColor(0, 255, 0);
  292.     blue= new_RGBColor(0, 0, 255);
  293.     }
  294.  
  295.     for (byte *p= (byte*)buf; *p != '\0'; p++) {
  296.     if (*p == '@') {
  297.         if (*(p+1) && strchr("OUSBIPrgbx[]|_*<>+-^v", *(p+1))) {
  298.         p++;
  299.         switch (*p) {
  300.         case 'P':
  301.             reader->SetFace(eFacePlain);
  302.             break;
  303.         case 'O':
  304.             reader->ToggleFace(eFaceOutline);
  305.             break;
  306.         case 'S':
  307.             reader->ToggleFace(eFaceShadow);
  308.             break;
  309.         case 'U':
  310.             reader->ToggleFace(eFaceUnderline);
  311.             break;
  312.         case 'B':
  313.             reader->ToggleFace(eFaceBold);
  314.             break;
  315.         case 'I':
  316.             reader->ToggleFace(eFaceItalic);
  317.             break;
  318.         case 'x':
  319.             reader->SetInk(gInkBlack);
  320.             break;
  321.         case 'r':
  322.             if (gColor)
  323.             reader->SetInk(red);
  324.             break;
  325.         case 'g':
  326.             if (gColor)
  327.             reader->SetInk(green);
  328.             break;
  329.         case 'b':
  330.             if (gColor)
  331.             reader->SetInk(blue);
  332.             break;
  333.         case '+':
  334.             reader->SetSize(reader->GetSize()+4);
  335.             break;
  336.         case '-':
  337.             reader->SetSize(reader->GetSize()-4);
  338.             break;
  339.         case '[':
  340.             reader->SetParaProp(eTxtPAlign, eTxtParaLeft);
  341.             break;
  342.         case ']':
  343.             reader->SetParaProp(eTxtPAlign, eTxtParaRight);
  344.             break;
  345.         case '|':
  346.             reader->SetParaProp(eTxtPAlign, eTxtParaCenter);
  347.             break;
  348.         case '_':
  349.             reader->SetParaProp(eTxtPAlign, eTxtParaJustified);
  350.             break;
  351.         case '<':
  352.             reader->SetParaProp(eTxtPLeft, 0);
  353.             break;
  354.         case '>':
  355.             reader->SetParaProp(eTxtPLeft, 20);
  356.             break;
  357.         case '^':
  358.             reader->SetParaProp(eTxtPSpaceBefore, 20);
  359.             break;
  360.         case 'v':
  361.             reader->SetParaProp(eTxtPSpaceBefore, 0);
  362.             break;
  363.         }
  364.          } else { 
  365.          p++;
  366.          if (!*p)
  367.              break;
  368.          reader->Append(*p);
  369.          }
  370.     } else 
  371.         reader->Append(*p);
  372.     }
  373.     reader->Flush();
  374.     SafeDelete(reader);
  375.     CheckInvariant(); 
  376. }
  377.  
  378. CharStyle *StyledText::GetCharStyle(int at)
  379. {
  380.     int d; // ???? -1
  381.     at= Math::Range(0, Size()-1, at);
  382.     return (CharStyle*) charStyles->RunAt(at, &d, &d, &d, &d);
  383. }
  384.  
  385. void StyledText::ReplaceCharStyles(RunArray *st, int from, int to)
  386. {
  387.     if (to-from != st->Size())
  388.     Error("ReplaceCharStyle", "RunArray does not match text");
  389.     charStyles->Paste(st, from, to);
  390.     
  391.     GetMarkList()->RangeChanged(from, to-from);
  392.     Send(cIdNone, eTextChangedRange, changeRec(from, to));     
  393. }
  394.  
  395. void StyledText::ReplaceParaStyles(RunArray *st, int from, int to)
  396. {
  397.     if (to-from != st->Size())
  398.     Error("ReplaceParaStyles", "RunArray does not match text");
  399.     paraStyles->Paste(st, from, to);
  400.     
  401.     GetMarkList()->RangeChanged(from, to-from);
  402.     Send(cIdNone, eTextChangedRange, changeRec(from, to));     
  403. }
  404.  
  405. void StyledText::ResetCurrentCharStyle()
  406. {
  407.     if (End() != 0)
  408.     applyStyleHere= FALSE;
  409. }
  410.  
  411. CharStyle *StyledText::GetCurrentCharStyle()
  412. {
  413.     if (applyStyleHere)
  414.     return styleHere;
  415.     return 0;    
  416. }
  417.  
  418. RunArray *StyledText::GetCharStyles()
  419. {
  420.     return charStyles; 
  421. }
  422.  
  423. RunArray *StyledText::GetParaStyles()
  424. {
  425.     return paraStyles; 
  426. }
  427.  
  428. RunArray *StyledText::SetCharStyles(RunArray *st)
  429. {
  430.     if (st->Size() != Size())
  431.     Error("StyledText", "StyleArray does not correspond to the text");
  432.  
  433.     RunArray *old= charStyles;
  434.     charStyles= st;
  435.     return old;
  436. }
  437.  
  438. RunArray *StyledText::SetParaStyles(RunArray *st)
  439. {
  440.     if (st->Size() != Size())
  441.     Error("StyledText", "StyleArray does not correspond to the text");
  442.  
  443.     RunArray *old= paraStyles;
  444.     paraStyles= st;
  445.     return old;
  446. }
  447.  
  448. void StyledText::SetParaStyle(TxtParaProp what, int from, int to, const ParaDesc &pd)
  449. {
  450.     int pfl, ptr, dd;   // paragraph ranges
  451.     int start, end, size;
  452.  
  453.     // find start and end of paragraphs
  454.     GetParaRange(from, &pfl, &dd);
  455.     if (to == from)
  456.     ptr= dd;
  457.     else if (IsPara((*this)[to-1]))
  458.     ptr= to;
  459.     else
  460.     GetParaRange(to, &dd, &ptr);
  461.     
  462.     ParaStyle **spp;
  463.     RunArray newStyles(2);
  464.     paraStyles->Copy(&newStyles, pfl, ptr);
  465.     RunArrayIter next(&newStyles);
  466.     while (spp= (ParaStyle**)next.RunPtr(&start, &end, &size)) 
  467.     *spp= gParaStyles->ChangeProperty(*spp, what, pd);
  468.     paraStyles->Paste(&newStyles, pfl, ptr);
  469.     
  470.     GetMarkList()->RangeChanged(pfl, ptr-pfl);
  471.     bool pagination= ((what & eTxtPNoBreak) == eTxtPNoBreak)
  472.              || ((what & eTxtPKeepNext) == eTxtPKeepNext);
  473.     Send(cIdNone, eTextChangedRange, changeRec(pfl, ptr, 0, pagination));     
  474. }
  475.  
  476. ParaStyle *StyledText::GetParaStyle(int at)
  477. {
  478.     int d; 
  479.     at= Math::Range(0, Size()-1, at);
  480.     return (ParaStyle*) paraStyles->RunAt(at, &d, &d, &d, &d);
  481. }
  482.  
  483.